package com.sx.frontend.protocal376_1.util;

import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

public class KoineBytesUtil {

	private final static char[] mChars = "0123456789ABCDEF".toCharArray();

	private final static String mHexStr = "0123456789ABCDEF";

	private static final String UNI_CODE = "ISO-8859-1";

	private static ByteBuffer buffer = ByteBuffer.allocate(8);

	public static int integerToByte(int number) {
		int tmp = number & 0xff ;
		return (tmp & 0x80) == 0 ? tmp : tmp - 256;
	}

	// byte 与 int 的相互转换
	public static byte intToByte(int x) {
		return (byte) x;
	}

	public static int byteToInt(byte b) {
		// Java 总是把 byte 当做有符处理；我们可以通过将其和 0xFF 进行二进制与得到它的无符值
		return b & 0xFF;
	}

	// byte 数组与 int 的相互转换
	public static int byteArrayToInt(byte[] b) {
		return b[3] & 0xFF | (b[2] & 0xFF) << 8 | (b[1] & 0xFF) << 16 | (b[0] & 0xFF) << 24;
	}

	public static byte[] intToByteArray(int a) {
		return new byte[] { (byte) ((a >> 24) & 0xFF), (byte) ((a >> 16) & 0xFF), (byte) ((a >> 8) & 0xFF), (byte) (a & 0xFF) };
	}

	/**
	 * 将整型转换为字节数组~
	 *
	 * @param integer
	 * @return
	 */
	public static byte[] int2bytes(int integer) {
		byte[] bytes = new byte[4];
		bytes[0] = (byte) (integer & 0xff); // 最低位
		bytes[1] = (byte) ((integer >> 8) & 0xff); // 次低位
		bytes[2] = (byte) ((integer >> 16) & 0xff); // 次高位
		bytes[3] = (byte) (integer >>> 24); // 最高位，无符号右移。
		return bytes;
	}

	public static int int2HexStr(String integer) {
		return Integer.decode("0x" + integer);
	}

	// byte 数组与 long 的相互转换
	public static byte[] longToBytes(long x) {
		buffer.putLong(0, x);
		return buffer.array();
	}

	public static long bytesToLong(byte[] bytes) {
		buffer.put(bytes, 0, bytes.length);
		buffer.flip();// need flip
		return buffer.getLong();
	}

	public static StringBuffer byteToHexString(StringBuffer hexBuffer, byte bytes) {
		hexBuffer.append(Character.forDigit((bytes & 0xF0) >> 4, 16)); // 转化高四位
		hexBuffer.append(Character.forDigit((bytes & 0x0F), 16)); // 转化低四位
		// hexBuilder.append(' '); // 加一个空格将每个字节分隔开
		return hexBuffer;

	}

	/**
	 * Convert hex string to byte[]
	 *
	 * @param hexString the hex string
	 * @return byte[]
	 */
	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	public static byte[] hexStringToBytes(String hexString, int length) {
		return hexStringToBytes(patchHexString(hexString, length));
	}

	/**
	 * HEX字符串前补0，主要用于长度位数不足。
	 *
	 * @param str String 需要补充长度的十六进制字符串
	 * @param maxLength int 补充后十六进制字符串的长度
	 * @return 补充结果
	 */
	static public String patchHexString(String str, int maxLength) {
		String temp = "";
		for (int i = 0; i < maxLength - str.length(); i++) {
			temp = "0" + temp;
		}
		str = (temp + str).substring(0, maxLength);
		return str;
	}

	static public String patchEndHexString(String str, int maxLength) {
		String temp = "";
		for (int i = 0; i < maxLength - str.length(); i++) {
			temp = temp + "0";
		}
		str = (str + temp).substring(0, maxLength);
		return str;
	}

	/**
	 * bytes字符串转换为Byte值
	 *
	 * @param src String Byte字符串，每个Byte之间没有分隔符(字符范围:0-9 A-F)
	 * @return byte[]
	 */
	public static byte[] hexStr2Bytes(String src) {
		/* 对输入值进行规范化整理 */
		src = src.trim().replace(" ", "").toUpperCase(Locale.US);
		// 处理值初始化
		int m = 0, n = 0;
		int iLen = src.length() / 2; // 计算长度
		byte[] ret = new byte[iLen]; // 分配存储空间

		for (int i = 0; i < iLen; i++) {
			m = i * 2 + 1;
			n = m + 1;
			ret[i] = (byte) (Integer.decode("0x" + src.substring(i * 2, m) + src.substring(m, n)) & 0xFF);
		}
		return ret;
	}

	public static String xor(String content) {
		content = change(content);
		String[] b = content.split(" ");
		int a = 0;
		for (int i = 0; i < b.length; i++) {
			a = a ^ Integer.parseInt(b[i], 16);
		}
		if (a < 10) {
			StringBuffer sb = new StringBuffer();
			sb.append("0");
			sb.append(a);
			return sb.toString();
		}
		return Integer.toHexString(a);
	}

	/*
	 * public static byte checkXOR(HeaderInfo headerInfo) {
	 *
	 * byte[] verifyByte = new byte[] { getXor(headerInfo.getFunctionId()), getXor(headerInfo.getBodyAttri()),
	 * getXor(headerInfo.getSerialNum()), getXor(headerInfo.getProductId()), getXor(headerInfo.getContent() != null ?
	 * headerInfo.getContent() : new byte[] { 0 }) };
	 *
	 * return getXor(verifyByte); }
	 */
	public static byte getXor(byte[] datas) {

		byte temp = datas[0];

		for (int i = 1; i < datas.length; i++) {
			temp ^= datas[i];
		}
		return temp;
	}

	public static String change(String content) {
		String str = "";
		for (int i = 0; i < content.length(); i++) {
			if (i % 2 == 0) {
				str += " " + content.substring(i, i + 1);
			} else {
				str += content.substring(i, i + 1);
			}
		}
		return str.trim();
	}

	/**
	 * 16进制转Ascii
	 * @param hexStr
	 * @return
	 */
	public static String hexToAscii(String hexStr) {
		StringBuilder output = new StringBuilder("");
		for (int i = 0; i < hexStr.length(); i += 2) {
			String str = hexStr.substring(i, i + 2);
			output.append((char) Integer.parseInt(str, 16));
		}
		return output.toString();
	}

	/**
	 * 将16进制字符串转换成汉字
	 * @param str
	 * @return
	 */
	public static String deUnicode(String str) {
		byte[] bytes = new byte[str.length() / 2];
		byte tempByte = 0;
		byte tempHigh = 0;
		byte tempLow = 0;
		for (int i = 0, j = 0; i < str.length(); i += 2, j++) {
			tempByte = (byte) (((int) str.charAt(i)) & 0xff);
			if (tempByte >= 48 && tempByte <= 57) {
				tempHigh = (byte) ((tempByte - 48) << 4);
			} else if (tempByte >= 97 && tempByte <= 101) {
				tempHigh = (byte) ((tempByte - 97 + 10) << 4);
			}
			tempByte = (byte) (((int) str.charAt(i + 1)) & 0xff);
			if (tempByte >= 48 && tempByte <= 57) {
				tempLow = (byte) (tempByte - 48);
			} else if (tempByte >= 97 && tempByte <= 101) {
				tempLow = (byte) (tempByte - 97 + 10);
			}
			bytes[j] = (byte) (tempHigh | tempLow);
		}
		String result = null;
		try {
			result = new String(bytes, "GBK");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	public static String hexToAscii_two(String s) {
		int n = s.length();
		StringBuilder sb = new StringBuilder(n / 2);
		for (int i = 0; i < n; i += 2) {
			char a = s.charAt(i);
			char b = s.charAt(i + 1);
			sb.append((char) ((hexToInt(a) << 4) | hexToInt(b)));
		}
		return sb.toString();
	}

	private static int hexToInt(char ch) {
		if ('a' <= ch && ch <= 'f') { return ch - 'a' + 10; }
		if ('A' <= ch && ch <= 'F') { return ch - 'A' + 10; }
		if ('0' <= ch && ch <= '9') { return ch - '0'; }
		throw new IllegalArgumentException(String.valueOf(ch));
	}



	/**
	 * Convert char to byte
	 *
	 * @param c char
	 * @return byte
	 */
	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	/**
	 * 将字节数组转换为整型~
	 *
	 * @param bytes
	 * @return
	 */
	public static int bytes2int(byte[] bytes) {
		// 一个 byte 数据左移 24 位变成 0x??000000，再右移 8 位变成 0x00??0000（| 表示按位或）
		int integer = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00) | ((bytes[2] << 24) >>> 8) | (bytes[3] << 24);
		return integer;
	}

	/*
	 * 字符串转16进制字符串
	 */
	public static String string2HexString(String s) throws Exception {
		String r = bytes2HexString(string2Bytes(s));
		return r;
	}

	/*
	 * 字符串转字节数组
	 */
	public static byte[] string2Bytes(String s) {
		byte[] r = s.getBytes();
		return r;
	}

	/*
	 * 字节数组转16进制字符串
	 */
	public static String bytes2HexString(byte[] b) {
		String r = "";

		for (int i = 0; i < b.length; i++) {
			String hex = Integer.toHexString(b[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			r += hex.toUpperCase();
		}

		return r;
	}

	/**
	 * bytes转换成十六进制字符串
	 *
	 * @param b byte[] byte数组
	 * @param iLen int 取前N位处理 N=iLen
	 * @return String 每个Byte值之间空格分隔
	 */
	public static String byte2HexStr(byte[] b, int iLen) {

		StringBuilder sb = new StringBuilder();
		for (int n = 0; n < iLen; n++) {
			sb.append(mChars[(b[n] & 0xFF) >> 4]);
			sb.append(mChars[b[n] & 0x0F]);
			sb.append(' ');
		}
		return sb.toString().trim().toUpperCase(Locale.US);
	}

	/**
	 * Convert byte[] to hex string.这里我们可以将byte转换成int，然后利用Integer.toHexString(int)来转换成16进制字符串。
	 *
	 * @param src byte[] data
	 * @return hex string
	 */
	public static String bytesToHexString(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder();
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}

	/**
	 * @Title:intToHexString
	 * @Description:10进制数字转成16进制
	 * @param a 转化数据
	 * @param len 占用字节数
	 * @return @throws
	 */
	public static String intToHexString(int a, int len) {
		len <<= 1;
		String hexString = Integer.toHexString(a);
		int b = len - hexString.length();
		if (b > 0) {
			for (int i = 0; i < b; i++) {
				hexString = "0" + hexString;
			}
		}
		return hexString;
	}

	public static byte[] convertToHexBytes(int a, int len) {
		return hexStringToBytes(intToHexString(a, len));
	}

/*	public static String readSpecialHexBytes(ByteBuf buf, int dataLength) {
		buf.retain();
		byte[] dataArray = new byte[dataLength];
		buf.readBytes(dataArray);
		buf.resetReaderIndex();
		String dataHexString = bytes2HexString(dataArray);

		return dataHexString;
	}*/

/*	public static String readSpecialLocationBytes(ByteBuf buf, int start, int dataLength) {
		byte[] dataArray = new byte[dataLength];

		// 数据末尾
		buf.getBytes(start, dataArray, 0, dataLength);
		return bytes2HexString(dataArray);
	}*/

	public static int hexStrToDec(String hexStr) {
		Long dec_num = Long.parseLong(hexStr, 16);

		return dec_num.intValue();
	}

	/**
	 * 有符号16进制转10进制
	 * @param strHex
	 * @return
	 */
	public static int signedHexToDec(String strHex){
		if(strHex.length()==0){
			return 0;
		}
		int x = 0;
		//带符号十六进制转换十进制
		String fristNum = strHex.substring(0, 1);
		String hexStr2Byte = parseHexStr2Byte(fristNum);
		String flag = hexStr2Byte.substring(0, 1);
		if("1".equals(flag)){
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < strHex.length(); i++) {
				String num = strHex.substring(i, i+1);
				int decNum = Integer.parseInt(num,16);
				int a = decNum^15;
				sb.append(intToHex(a));
			}
			x = -Integer.parseInt(sb.toString(),16)-1;
		}else{
			x = Integer.parseInt(strHex,16);
		}

		return x;

	}

	//十进制转16进制
	private static String intToHex(int n) {
		StringBuffer s = new StringBuffer();
		String a;
		char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
		while(n != 0){
			s = s.append(b[n%16]);
			n = n/16;
		}
		a = s.reverse().toString();
		return a;
	}

	/**
	 * 将16进制转换为二进制
	 *
	 * @param hexStr
	 * @return
	 */
	public static String parseHexStr2Byte(String hexStr) {
		if (hexStr.length() == 0)
			return null;
		int sint=Integer.valueOf(hexStr, 16);
		//十进制在转换成二进制的字符串形式输出!
		String bin=Integer.toBinaryString(sint);
		for (int i = bin.length(); i < 4; i++) {
			bin = "0"+bin;
		}
		return bin;
	}


	public static String hexStrToSigned(String hexStr){
		return String.valueOf((Integer.valueOf(hexStr,16).shortValue())/256-1);
	}

	public static String fromBytes(byte[] bytes) {
		try {
			return new String(bytes, UNI_CODE);
		} catch (UnsupportedEncodingException e) {
			// TODO - either handle the exception or throw a New Horizon domain exception
			e.printStackTrace();
		}
		return null;
	}

	public static byte[] toBytes(String transformedData) {
		if (StringUtils.isBlank(transformedData)) {
			return null;
		}
		try {
			return transformedData.getBytes(UNI_CODE);
		} catch (UnsupportedEncodingException e) {
			// TODO - either handle the exception or throw a New Horizon domain exception
			e.printStackTrace();
		}
		return null;
	}

/*	public static String bytebufToStr(ByteBuf buf) {
		byte[] bytes = ByteBufUtil.getBytes(buf);
		buf.clear();
		return fromBytes(bytes);
	}*/

	// with some error, still need to change
/*	public static ByteBuf roolBackToOriginalBytes(ByteBuf byteBuf) {

		String hexDump = ByteBufUtil.hexDump(byteBuf);
		hexDump.replace("8E02", "8F");
		hexDump.replace("8E01", "8E");

		ByteBuf resultBytebuf = Unpooled.buffer(100);
		resultBytebuf.writeBytes(hexStr2Bytes(hexDump));

		return resultBytebuf;
	}*/

	public static byte[] intToHexBytes(int dataValue, int size) {
		return hexStringToBytes(intToHexString(dataValue, size));
	}

	public static BigDecimal hexStrToDecimal(String hexData, int precision) {
		BigDecimal decimal = new BigDecimal(new BigInteger(hexData, 16));
		BigDecimal precisionDecimal = new BigDecimal(10).pow(2);
		BigDecimal value = decimal.divide(precisionDecimal).setScale(precision, RoundingMode.DOWN);
		return value;
	}

	public static BigDecimal hexDecToDecimal(String hexData, int precision) {
		BigDecimal decimal = new BigDecimal(hexData);
		BigDecimal precisionDecimal = new BigDecimal(10).pow(2);
		BigDecimal value = decimal.divide(precisionDecimal).setScale(precision, RoundingMode.DOWN);
		return value;
	}

	public static byte[] byteMergerAll(byte[]... values) {
		int length_byte = 0;
		for (int i = 0; i < values.length; i++) {
			length_byte += values[i].length;
		}
		byte[] all_byte = new byte[length_byte];
		int countLength = 0;
		for (int i = 0; i < values.length; i++) {
			byte[] b = values[i];
			System.arraycopy(b, 0, all_byte, countLength, b.length);
			countLength += b.length;
		}
		return all_byte;
	}

	/**
	 *
	 * Object src--------原数组
	 * int srcPos-------原数组开始位置
	 * Object dest---------目的数组
	 * int destPos-------目的数组开始位置
	 * int length--------要复制的元素个数
	 *
	 * @param values
	 * @param start
	 * @param dataLength
	 * @return
	 */
	public static byte[] copyBytes(byte[] values, int start, int dataLength) {
		byte[] resultBytes = new byte[dataLength];
		System.arraycopy(values, start, resultBytes, 0, dataLength);
		return resultBytes;
	}

	public static String chineseToHexString(String targetString) {
		byte[] chineseBytes;
		try {
			chineseBytes = targetString.getBytes("gb2312"); // 解码
			return bytes2HexString(chineseBytes);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 存放16进制字符串,字符串2为 2为存
	 * @param hexString
	 * @return
	 */
	public static List<String> parseArrayList(String hexString) {
		List<String> strings = new ArrayList<>();
		for (int i = 0; i < hexString.length() / 2; i++) {
			int index = i * 2;
			strings.add(hexString.substring(index, index + 2));
		}
		return strings;
	}

	public static String[] strChange(String str1[],  int start, int end){

		int k = end - start;
		String str2[] = new String[k];
		for(int i = start, j=0 ; i<end && j<k; i++,j++){
			str2[j] = str1[i];
		}

		return str2;
	}


	// ------- Instance Methods (private) --------------------------------------

	private static byte[] replaceBytes(byte[] bytes, byte[] byteSource, byte[] byteTarget) {
		byte[] resultBytes = null;
		for (int i = 0; i < bytes.length; i++) {
			if (Arrays.equals(new byte[] { bytes[i] }, byteSource)) {
				resultBytes = rebuildBytes(bytes, byteTarget, i);
				bytes = resultBytes;
			} else {
				resultBytes = bytes;
			}
		}
		return resultBytes;
	}

	private static byte[] rebuildBytes(byte[] bytes, byte[] byteTarget, int i) {
		byte[] resultBytes = new byte[bytes.length + byteTarget.length - 1];
		System.arraycopy(bytes, 0, resultBytes, 0, bytes.length);
		System.arraycopy(byteTarget, 0, resultBytes, i, byteTarget.length);
		System.arraycopy(bytes, i + byteTarget.length - 1, resultBytes, i + 2, resultBytes.length - i - 2);
		return resultBytes;
	}


}
